#include <stdio.h>
#include <stdlib.h>
#include <string.h> 
#include "matrix_operations/matrix_operations.h"
#include "utils/utils.h"

int main()
{
    // 定义矩阵
    const int ROWS = 28;
    const int COLS = 28;
    const int MATRIX_SIZE = 784;
    const int HIDDEN_LAYER_SIZE = 128;
    const int OUTPUT_SIZE = 10;

    double A[ROWS][COLS];
    double B[1][MATRIX_SIZE];
    double D[1][HIDDEN_LAYER_SIZE];
    double F[1][HIDDEN_LAYER_SIZE];
    double G[1][HIDDEN_LAYER_SIZE];
    double H[1][HIDDEN_LAYER_SIZE];
    double L[1][OUTPUT_SIZE];
    double S[1][OUTPUT_SIZE];

    // 用户交互循环
    while (1)
    {
        char file_path[256];
        printf("Please input filenames：");
        scanf("%s", file_path);

        // 检查文件是否存在
        FILE *fp = fopen(file_path, "rb");
        if (fp == NULL)
        {
            printf("Invalid file.\n");
            return 1;
        }
        fclose(fp);

        // 读取图像文件
        pgm_to_matrix(const char* file_path, int ROWS, int COLS, Matrix A);

        // 将图像矩阵转换为向量
        matrix_to_vector(int ROWS, int COLS, Matrix A, Vector B);

        // 应用第一隐藏层权重和偏置
        double W1_data[1][100352];
        Matrix W1_matrix = read_txt_data("input_files/W1.txt");
        double C[ROWS][HIDDEN_LAYER_SIZE];
        vector_to_matrix(ROWS, HIDDEN_LAYER_SIZE, W1_data, C);
        Matrix B_matrix, C_matrix, D_matrix;

       // 初始化矩阵 B, C, D
        Matrix B_matrix = {1, MATRIX_SIZE, (float *)B[0]};
        Matrix C_matrix = {ROWS, HIDDEN_LAYER_SIZE, (float *)C[0]};
        Matrix D_matrix = {1, HIDDEN_LAYER_SIZE, NULL};

        // 执行矩阵乘法
        matrix_mul(B_matrix, C_matrix, D_matrix);

        // 将结果复制回原始 D 矩阵
       memcpy(D[0], D_matrix.data, HIDDEN_LAYER_SIZE * sizeof(double));
        // 释放内存
        free(B_matrix.data);
        free(C_matrix.data);
        free(D_matrix.data);

        // 添加偏置
        double B1_data[1][HIDDEN_LAYER_SIZE];
        Matrix B1_matrix = read_txt_data("input_files/B1.txt");

        // 初始化矩阵 B1, F
       Matrix B1_matrix = {1, HIDDEN_LAYER_SIZE, (float *)B1_data[0]};
        Matrix F_matrix = {1, HIDDEN_LAYER_SIZE, NULL};

        // 执行矩阵加法
        matrix_add(D_matrix, B1_matrix, F_matrix);

        // 将结果复制回原始 F 矩阵
        memcpy(F[0], F_matrix.data, HIDDEN_LAYER_SIZE * sizeof(double));

        // 释放内存
        free(D_matrix.data);
        free(B1_matrix.data);
        free(F_matrix.data);

        // 激活函数
        active_function(HIDDEN_LAYER_SIZE, F, G);

        // 应用第二隐藏层权重和偏置
        double W2_data[1][1280];
        Matrix W2_matrix = read_txt_data("input_files/W2.txt");
        double C2[HIDDEN_LAYER_SIZE][OUTPUT_SIZE];
        vector_to_matrix(HIDDEN_LAYER_SIZE, OUTPUT_SIZE, W2_data, C2);
        
        //初始化矩阵G，C2，L
        Matrix G_matrix = {1, HIDDEN_LAYER_SIZE, (float *)&G[0][0]};
        Matrix C2_matrix = {HIDDEN_LAYER_SIZE, OUTPUT_SIZE, (float *)&C2[0][0]};
        Matrix L_matrix = {1, OUTPUT_SIZE, NULL};

        // 执行矩阵乘法
        matrix_mul(G_matrix, C2_matrix, L_matrix);

        // 将结果复制回原始 L 矩阵
        memcpy(L[0], L_matrix.data, OUTPUT_SIZE * sizeof(double));
        // 释放内存
        free(L_matrix.data);

        // 添加偏置
        double B2_data[1][OUTPUT_SIZE];
        read_txt_data("input_files/B2.txt", B2_data);
        Matrix B2_matrix = {1, OUTPUT_SIZE, (float *)B2_data[0]};
        Matrix L_result_matrix = {1, OUTPUT_SIZE, NULL};

        // 执行矩阵加法
        matrix_add(L_matrix, B2_matrix, L_result_matrix);

        // 将结果复制回原始 L 矩阵
        memcpy(L[0], L_result_matrix.data, OUTPUT_SIZE * sizeof(double));

        // 释放内存
        free(L_result_matrix.data);

      
        // SoftMax
        soft_max(1, OUTPUT_SIZE, L, S);

        // 输出识别结果
        int digit = 0;
        double max_val = S[0][0];
        for (int i = 1; i < OUTPUT_SIZE; i++)
        {
            if (S[0][i] > max_val)
            {
                max_val = S[0][i];
                digit = i;
            }
        }
        printf("%s: %d\n", file_path, digit);

        // 询问是否继续
        char continue_choice;
        printf("Do you want to continue？Please input [Y or N]: ");
        scanf(" %c", &continue_choice);
        if (continue_choice != 'Y' && continue_choice != 'y')
        {
            break;
        }
    }

    return 0;
}